Namespace ShapeLibrary

    Friend Class Needle
        Inherits ShapeLibrary.ShapeContainer

        Private m_colour As Color = SystemColors.WindowText
        Private m_fillColour As Color = SystemColors.WindowText
        Private m_lineColour As Color = SystemColors.WindowText
        Private m_fill As Boolean = False
        Private m_bounds As Rectangle = New Rectangle(0, 0, 150, 150)
        Private m_topDiff As Single = 0.5
        Private m_botDiff As Single = 5
        Private m_length As Single = 50
        Private m_centerX As Single = 75
        Private m_centerY As Single = 75
        Private m_angle As Double = 0

        Private m_start As Double = 90
        Private m_end As Double = 315

        Private m_threshold As Double = 0.5
        Private m_warning As Double = 0.75
        Private m_StartValue As Double = 0
        Private m_EndValue As Double = 1
        Private m_value As Double = 0.5

        Private m_increments As Integer = 10
        Private m_SubIncrements As Integer = 5
        Private m_needleTocircle As Double = 1.2
        Private m_pointsDist As Single = 1.2
        Private m_pointsLen As Single = m_length / 5

        Private m_pointsTxt() As String = Nothing
        Private m_text As String = ""
        Private m_allign As StringAlignment = StringAlignment.Center

        Friend WithEvents Ellipse1 As ShapeLibrary.Ellipse
        Friend WithEvents Polygon2 As ShapeLibrary.Polygon
        Friend WithEvents TextValue As ShapeLibrary.Text
        Private Lines() As ShapeLibrary.Line
        Private SubLines() As ShapeLibrary.Line
        Private TextPoints() As ShapeLibrary.Text

        Private mGraphicManager As BufferedGraphicsContext
        Private mBackgroundBuffer As BufferedGraphics

        Friend Event onRedrewPoints(ByRef Sender As Needle)


        Friend Sub drawGaugePoints(Optional ByVal iG As Graphics = Nothing)
            ' If m_increments <> 0 And Not IsNothing(m_pointsTxt) Then
            ReDim Lines(0 To m_increments - 1)
            ReDim SubLines(0 To ((m_increments - 1) * 4) - 1)

            Dim f_angle As Double
            Dim f_tmp As Integer
            For i As Integer = 0 To m_increments - 1
                f_angle = (((((m_end - m_start) / (m_increments - 1)) * i) + m_start) * Math.PI) / 180
                Lines(i) = New ShapeLibrary.Line()
                Lines(i).Width = 2
                If ((m_EndValue - m_StartValue) * ((i / (m_increments - 1)))) <= m_threshold Then
                    Lines(i).Color = Drawing.Color.Red
                ElseIf ((m_EndValue - m_StartValue) * ((i / (m_increments - 1)))) <= m_warning Then
                    Lines(i).Color = Drawing.Color.Blue
                Else
                    Lines(i).Color = m_lineColour

                End If
                Lines(i).StartPoint = New PointF(((m_length * m_pointsDist) * System.Math.Sin(f_angle)) + m_centerX + m_bounds.X, ((m_length * m_pointsDist) * System.Math.Cos(f_angle)) + m_centerY + m_bounds.Y)
                Lines(i).EndPoint = New PointF((((m_length * m_pointsDist) + m_pointsLen) * System.Math.Sin(f_angle)) + m_centerX + m_bounds.X, (((m_length * m_pointsDist) + m_pointsLen) * System.Math.Cos(f_angle)) + m_centerY + m_bounds.Y)
                If i <= m_increments - 2 Then
                    For g As Integer = 0 To 3
                        f_angle += ((((m_end - m_start) / (m_increments - 1)) / 5) * Math.PI) / 180
                        f_tmp = ((i * 4) + g)
                        SubLines(f_tmp) = New ShapeLibrary.Line
                        SubLines(f_tmp).Width = 1.5
                        If ((m_EndValue - m_StartValue) * ((i + (g * 0.2)) / (m_increments - 1))) < m_threshold Then
                            SubLines(f_tmp).Color = Drawing.Color.Red
                        ElseIf ((m_EndValue - m_StartValue) * ((i + (g * 0.2)) / (m_increments - 1))) < m_warning Then
                            SubLines(f_tmp).Color = Drawing.Color.Blue
                        Else
                            SubLines(f_tmp).Color = m_lineColour
                        End If
                        SubLines(f_tmp).StartPoint = New PointF((((m_length * m_pointsDist) + (m_pointsLen / 3)) * System.Math.Sin(f_angle)) + m_centerX + m_bounds.X, (((m_length * m_pointsDist) + (m_pointsLen / 3)) * System.Math.Cos(f_angle)) + m_centerY + m_bounds.Y)
                        SubLines(f_tmp).EndPoint = New PointF((((m_length * m_pointsDist) + m_pointsLen) * System.Math.Sin(f_angle)) + m_centerX + m_bounds.X, (((m_length * m_pointsDist) + m_pointsLen) * System.Math.Cos(f_angle)) + m_centerY + m_bounds.Y)
                    Next
                End If
            Next

            Dim f_x As Single = Me.Bounds.Width / 2 + Me.Bounds.X
            If m_allign = StringAlignment.Near Then f_x -= (Me.Bounds.Width / 8)
            Me.TextValue = New Text(m_value \ 1 & " " & m_text, New PointF(f_x, Me.Bounds.Height / 1.35 + Me.Bounds.Y), Drawing.Color.Black, New Font("Verdana", 10, FontStyle.Bold, GraphicsUnit.Pixel), m_allign)


            ' Try
            'For i As Integer = 2 To 50
            Me.Shapes.Clear()
            Me.Shapes.AddRange(New ShapeLibrary.Shape() {Me.Polygon2, Me.Ellipse1, Me.TextValue})
            ' Next
            'Catch ex As Exception
            'End Try

            Dim f_txtStPoint As PointF
            Dim f_txt As Text
            If Not IsNothing(m_pointsTxt) AndAlso UBound(m_pointsTxt) >= 1 Then
                ReDim TextPoints(0 To UBound(m_pointsTxt))

                If UBound(m_pointsTxt) >= 1 Then
                    For i As Integer = 0 To UBound(m_pointsTxt)
                        f_angle = (((((m_end - m_start) / (UBound(m_pointsTxt))) * i) + m_start) * Math.PI) / 180
                        f_txtStPoint = New PointF((((m_length * m_pointsDist) - m_pointsLen) * System.Math.Sin(f_angle)) + m_centerX + m_bounds.X, (((m_length * m_pointsDist) - m_pointsLen) * System.Math.Cos(f_angle)) + m_centerY + m_bounds.Y)
                        f_txt = New Text(m_pointsTxt(m_pointsTxt.Length - 1 - i), f_txtStPoint, New Font("Verdana", 8, FontStyle.Regular, GraphicsUnit.Pixel))

                        If ((m_EndValue - m_StartValue) * (i) / UBound(m_pointsTxt)) < m_threshold Then
                            f_txt.Color = Drawing.Color.Red
                        ElseIf ((m_EndValue - m_StartValue) * (i) / UBound(m_pointsTxt)) < m_warning Then
                            f_txt.Color = Drawing.Color.Blue
                        Else
                            f_txt.Color = m_lineColour
                        End If
                        TextPoints(i) = f_txt
                        '   Me.Shapes.Add(f_txt)
                    Next
                End If
            End If

            If Not IsNothing(iG) Then
                For i As Integer = 0 To UBound(Lines)
                    Lines(i).Draw(iG)
                Next
                For i As Integer = 0 To UBound(SubLines)
                    SubLines(i).Draw(iG)
                Next
                If Not IsNothing(TextPoints) Then
                    For i As Integer = 0 To UBound(TextPoints)
                        TextPoints(i).Draw(iG)
                    Next
                End If
            End If
            '  End If
            ' Me.Shapes.AddRange(Lines)
            ' Me.Shapes.AddRange(SubLines)
        End Sub
        Public Property Threshold() As Double
            Get
                Return m_threshold
            End Get
            Set(ByVal value As Double)
                If value <= m_EndValue And value >= m_StartValue Then m_threshold = value
                RaiseEvent onRedrewPoints(Me) 'drawGaugePoints()
            End Set
        End Property
        Public Property Warning() As Double
            Get
                Return m_warning
            End Get
            Set(ByVal value As Double)
                If value <= m_EndValue And value >= m_StartValue Then m_warning = value
                RaiseEvent onRedrewPoints(Me) 'drawGaugePoints()
            End Set
        End Property

        Public Property pointsStart() As Int16
            Get
                Return m_start
            End Get
            Set(ByVal value As Int16)
                m_start = value
                RaiseEvent onRedrewPoints(Me) 'drawGaugePoints()
            End Set
        End Property
        Public Property pointsEnd() As Integer
            Get
                Return m_end
            End Get
            Set(ByVal value As Integer)
                m_end = value
                RaiseEvent onRedrewPoints(Me) 'drawGaugePoints()
            End Set
        End Property
        Public Property Minimum() As Double
            Get
                Return m_StartValue
            End Get
            Set(ByVal value As Double)
                m_StartValue = value
            End Set
        End Property
        Public Property Maximum() As Double
            Get
                Return m_EndValue
            End Get
            Set(ByVal value As Double)
                m_EndValue = value
            End Set
        End Property
        Public Property Value() As Double
            Get
                Return m_value
            End Get
            Set(ByVal value As Double)

                m_value = value
                Me.Angle = ((1 - (m_value - m_StartValue) / (m_EndValue - m_StartValue)) * (m_end - m_start)) + m_start
                Me.TextValue.text = m_value \ 1 & " " & m_text
                SetNeedle(Angle)
            End Set
        End Property
        Public Property PointsText() As String
            Get
                Dim txt As String = ""
                If Not IsNothing(m_pointsTxt) Then
                    For i As Integer = 0 To UBound(m_pointsTxt)
                        txt &= m_pointsTxt(i) & ","
                    Next
                    Return Mid(txt, 1, txt.Length - 1)
                End If
                Return "nothing"
            End Get
            Set(ByVal value As String)
                If value.Length >= 1 Then
                    m_pointsTxt = value.Split(",")
                End If
                UserControl_Initialize()
                SetNeedle(m_angle)
            End Set
        End Property
        Public Property text() As String
            Get
                Return m_text
            End Get
            Set(ByVal value As String)
                m_text = value
                If Not IsNothing(TextValue) Then TextValue.text = m_value \ 1 & " " & m_text
            End Set
        End Property
        Public Property Allign() As StringAlignment
            Get
                Return m_allign
            End Get
            Set(ByVal value As StringAlignment)
                m_allign = value
            End Set
        End Property

        Public Property pointIncrements() As Integer
            Get
                Return m_increments
            End Get
            Set(ByVal value As Integer)
                m_increments = value
                RaiseEvent onRedrewPoints(Me) 'drawGaugePoints()
            End Set
        End Property
        Public Property lineColor() As Color
            Get
                Return m_lineColour
            End Get
            Set(ByVal value As Color)
                m_lineColour = value
                drawGaugePoints()
            End Set
        End Property
        <Description("The Fill colour of the Polygon.")> _
                Public Property fillColor() As Color
            Get
                Return m_fillColour
            End Get

            Set(ByVal Value As Color)
                m_fillColour = Value
                Polygon2.FillColor = m_fillColour
            End Set
        End Property
        Public Property NeedleToCircle() As Double
            Get
                Return m_needleTocircle
            End Get
            Set(ByVal value As Double)
                m_needleTocircle = value
                SetNeedle(m_angle)
            End Set
        End Property

        <Description("Fill the Polygon?")> _
                Public Property fill() As Boolean
            Get
                Return m_fill
            End Get

            Set(ByVal Value As Boolean)
                m_fill = Value
                Polygon2.FillPolygon = m_fill
                Ellipse1.Fill = m_fillColour
            End Set
        End Property

        <Description("The color of the Polygon.")> _
            Public Property Color() As Color
            Get
                Return m_colour
            End Get

            Set(ByVal Value As Color)
                m_colour = Value
                Polygon2.Color = m_colour
                Ellipse1.Color = m_colour
            End Set
        End Property

        '''
        ''' The bounds of the ellipse, in pixels.
        '''
        <Description("The bounds of the ellipse in pixels.")> _
        Public Property Bounds() As Rectangle
            Get
                Return m_bounds
            End Get

            Set(ByVal Value As Rectangle)
                m_bounds = Value
                UserControl_Initialize()
                SetNeedle(m_angle)
            End Set
        End Property
        <Description("The center offset of the needle")> _
        Public Property Length() As Single
            Get
                Return m_length
            End Get

            Set(ByVal Value As Single)
                m_length = Value
                SetNeedle(m_angle)
                m_pointsLen = m_length / 5
                UserControl_Initialize()
            End Set
        End Property
        <Description("The width of the needle at the outer end")> _
        Public Property OuterWidth() As Single
            Get
                Return m_topDiff
            End Get

            Set(ByVal Value As Single)
                m_topDiff = Value
                SetNeedle(m_angle)
            End Set
        End Property
        <Description("The width of the needle at the inner end")> _
        Public Property InnerWidth() As Single
            Get
                Return m_botDiff
            End Get

            Set(ByVal Value As Single)
                m_botDiff = Value
                SetNeedle(m_angle)
            End Set
        End Property
        <Description("The angle of the needle")> _
        Public Property Angle() As Double
            Get
                Return (m_angle * 180) / Math.PI
            End Get

            Set(ByVal Value As Double)
                m_angle = (Value * Math.PI) / 180
                SetNeedle(m_angle)
            End Set
        End Property

        Friend Sub SetNeedle(ByRef Angle_ As Double)
            Ellipse1.Bounds = New Rectangle(m_centerX + m_bounds.X - (m_botDiff * m_needleTocircle), m_centerY + m_bounds.Y - (m_botDiff * m_needleTocircle), (m_botDiff * (2 * m_needleTocircle)), (m_botDiff * (2 * m_needleTocircle)))
            Polygon2.Point1X = ((-m_botDiff) * System.Math.Cos(Angle_)) + ((0) * System.Math.Sin(Angle_)) + m_centerX
            Polygon2.Point1Y = ((0) * System.Math.Cos(Angle_)) - ((-m_botDiff) * System.Math.Sin(Angle_)) + m_centerY
            Polygon2.Point2X = ((m_botDiff) * System.Math.Cos(Angle_)) + ((0) * System.Math.Sin(Angle_)) + m_centerX
            Polygon2.Point2Y = ((0) * System.Math.Cos(Angle_)) - ((m_botDiff) * System.Math.Sin(Angle_)) + m_centerY
            Polygon2.Point3X = ((m_topDiff) * System.Math.Cos(Angle_)) + ((m_length) * System.Math.Sin(Angle_)) + m_centerX
            Polygon2.Point3Y = ((m_length) * System.Math.Cos(Angle_)) - ((m_topDiff) * System.Math.Sin(Angle_)) + m_centerY
            Polygon2.Point4X = ((-m_topDiff) * System.Math.Cos(Angle_)) + ((m_length) * System.Math.Sin(Angle_)) + m_centerX
            Polygon2.Point4y = ((m_length) * System.Math.Cos(Angle_)) - ((-m_topDiff) * System.Math.Sin(Angle_)) + m_centerY
        End Sub

        Private Sub UserControl_Initialize()
            m_centerX = (m_bounds.Width / 2) + m_bounds.X
            m_centerY = (m_bounds.Height / 2) + m_bounds.Y
            drawGaugePoints()
            Polygon2.Point1X = m_centerX - 5
            Polygon2.Point1Y = m_centerY
            Polygon2.Point2X = m_centerX + 5
            Polygon2.Point2Y = m_centerY
            Polygon2.Point3X = m_centerX + 0.5
            Polygon2.Point3Y = m_centerY - m_length
            Polygon2.Point4X = m_centerX - 0.5
            Polygon2.Point4y = m_centerY - m_length
            Polygon2.Bounds = m_bounds
            Ellipse1.Bounds = New Rectangle(m_centerX + m_bounds.X - (m_botDiff * 1.05), m_centerY + m_bounds.Y - (m_botDiff * 1.05), (m_botDiff * 2.1), (m_botDiff * 2.1))
            Ellipse1.Color = m_colour
            Ellipse1.Fill = m_fillColour
        End Sub


#Region " Component Designer generated code "

        Friend Sub New(ByVal Container As System.ComponentModel.IContainer)
            MyClass.New()

            'Required for Windows.Forms Class Composition Designer support
            Container.Add(Me)
        End Sub

        Friend Sub New()
            MyBase.New()

            'This call is required by the Component Designer.
            InitializeComponent()
            UserControl_Initialize()

            'Add any initialization after the InitializeComponent() call

        End Sub

        'Required by the Component Designer
        Private components As System.ComponentModel.Container


        'NOTE: The following procedure is required by the Component Designer
        'It can be modified using the Component Designer.
        'Do not modify it using the code editor.
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            Me.Polygon2 = New ShapeLibrary.Polygon
            Me.Ellipse1 = New ShapeLibrary.Ellipse
            '
            'Polygon2
            '
            Me.Polygon2.Bounds = New System.Drawing.Rectangle(2, 2, 150, 150)
            Me.Polygon2.Color = System.Drawing.Color.Red
            Me.Polygon2.FillColor = System.Drawing.SystemColors.WindowText
            Me.Polygon2.FillPolygon = False
            Me.Polygon2.Point1X = 0.0!
            Me.Polygon2.Point1Y = 0.0!
            Me.Polygon2.Point2X = 70.0!
            Me.Polygon2.Point2Y = 10.0!
            Me.Polygon2.Point3X = 80.0!
            Me.Polygon2.Point3Y = 30.0!
            Me.Polygon2.Point4X = 90.0!
            Me.Polygon2.Point4y = 45.0!
            '
            'Ellipse1
            '
            Me.Ellipse1.Bounds = New System.Drawing.Rectangle(67, 17, 100, 100)
            Me.Ellipse1.Color = System.Drawing.SystemColors.WindowText
            Me.Ellipse1.Fill = System.Drawing.SystemColors.MenuHighlight
            '
            'Needle
            '
            Me.Shapes.AddRange(New ShapeLibrary.Shape() {Me.Polygon2, Me.Ellipse1})

        End Sub

#End Region

    End Class
End Namespace